#!/bin/bash
#
# Get RetroAchievements information for Batocera
#
# @lbrpdx on Batocera Forums and Discord
#
# 20191124 - v2 with now outputs in XML format (for Batocera 5.25+)
# 20200113 - updated for retroachievements.org HTML changes
# 20200124 - added badges for each game played
# 20200304 - fixed a bug in rare cases where a RA game has no success icons
# 20200410 - updated for retroachievements.org HTML changes, again
# 20200625 - retroachievements.org HTML changes, again
# 20201104 - retroachievements.org HTML changes, again, again
#
# Usage:
# batocera-retroachievements-info
#
CONFIGFILE="/storage/.config/distribution/configs/distribution.conf"
TIMEOUT=4 # seconds before timeout (>2 sec)
USER=""

###############################
#
function usage() {
	echo "$0 username"
	echo " - where username is the RetroAchievements username you want to check out"
	exit 1
}

###############################
#
function process() {
	fn=$(date +"%s")
	tmpfile=/tmp/ra_$fn
	curl -H 'Cache-Control: no-cache' -m "$TIMEOUT" -o $tmpfile https://retroachievements.org/user/$USER 2>/dev/null
	if [ x"$?" != x0 ]; then
		echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
		echo "<retroachievements>"
		echo "  <lastrefresh>$fn</lastrefresh>"
		echo "  <error>RetroAchievements website is too slow to respond</error>"
		echo "</retroachievements>"
		exit 1;
	fi
	cat "$tmpfile" |  awk -v FS="(<div class='username'><span class='username'>|</div><div class='userpage recentlyplayed' >)" '{print $2}' | uniq > "$tmpfile"_2
	idcard=$(cat "$tmpfile" | sed -e "/^[[:blank:]]*$/d" | awk -v FS="(</span></div><br/?>Member Since: |<br/?>Account Type:)" '{print $2}' | uniq)
	parsedid=$(echo "$idcard" | sed -e "/^[[:blank:]]*$/d" | sed -e "s;\(.*\)<br>Last Activity: \(.*\);\1@\2;")
	avcompletion=$(cat "$tmpfile" | sed -e "/^[[:blank:]]*$/d" | awk -v FS="(</span><br/?>Average Completion: <b>|</b><br/?>Site Rank:)" '{print $2}' | sed -e "/^[[:blank:]]*$/d" | uniq)
	points=$(cat "$tmpfile"_2 | sed -e "/^[[:blank:]]*$/d" | awk -v FS="(</strong></a>&nbsp;|<span class='TrueRatio'>)" '{print $2}' |  sed -e "s;(\([0-9]*\) points);\1;")
	if [ x"$points" != x ] && [ "$points" -ge 1 ]; then
		rank=$(cat "$tmpfile"_2  | sed -e "/^[[:blank:]]*$/d" | awk -v FS="(globalRanking.php|<br/?><br/?>)" '{print $3}' | sed -e "s/\?[a-zA-Z0-9=&;']*>//" -e "s;</a>;;" -e "s;%).*;%);")
		## For future use: UserPic is RetroAchievements' user avatar - however the S3 bucket is protected.
		# UserPic=$(cat $tmpfile | grep 'meta property=.og:image. content=' | cut -d= -f3 | awk -F\' '{print $2}')
		# Workaround: use the line below
		UserPic="https://retroachievements.org/UserPic/$USER".png
		pic=""
		curl -H 'Cache-Control: no-cache' -m "$TIMEOUT" -f -s "$UserPic" >/dev/null 2>/dev/null
		if [ x"$?" == x0 ]; then
			pic="  <userpic>$UserPic</userpic>\n"
		fi
		echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
		echo "<retroachievements>"
		echo "  <lastrefresh>$fn</lastrefresh>"
		echo "  <username>$USER</username>"
		echo "  <totalpoints>$points</totalpoints>"
	        echo "  <rank>$rank</rank>"
	        echo "  <averagecompletion>$avcompletion</averagecompletion>"
		echo -ne "$pic"
		echo "$parsedid" | sed -e "s;\(.*\)@\(.*\);  <registered>\1</registered>\n  <lastactivity>\2</lastactivity>;"
		xmllint --html "$tmpfile" 2>/dev/null | grep '<a href="/[gG]ame/[0-9]*\">.*points.<br\?>' | sed -e "/^[[:blank:]]*$/d" | sed -e 's:\(<a href=\"/[gG]ame/[0-9]*\">.*\)points\.<br>:\1points\@\\\n:g;' > "$tmpfile"_2
		cat "$tmpfile"_2 | awk -v FS="(href=\"/[gG]ame/[0-9]*\">|@)" '{print $2}' | sed -e "s;</a><br/*>\(Last played[ 0-9:-]*\)<br/*>\(.*\);@\2@\1;" | sed -e "s;achievements, ;achievements@;" | sed -e "s;Earned ;;" | sed -e "/^[[:blank:]]*$/d" > "$tmpfile"_st
		cat "$tmpfile"_2 | grep -e 'div class="bb_inline" onmouseover' -e '^$' | sed "s:.*src=\"\(.*/Badge/.*\.png\)\".*:\1:" | sed "s;^$;https://batocera.org/favicon-64.png;" > "$tmpfile"_ba
		i=0
		if [ $(cat "$tmpfile"_ba | wc -l) -eq $(cat "$tmpfile"_st | wc -l) ]; then
			while IFS= read -r line || [[ -n "$line" ]]; do
				i=$((i+1))
				echo "$line" | sed -e "s;\(.*\)@\(.*\) achievements@\(.*\) points@Last played \(.*\);  <game>\n    <name>\1</name>\n    <achievements>\2</achievements>\n    <points>\3</points>\n    <lastplayed>\4</lastplayed>;"
				cat "$tmpfile"_ba | head -n "$i" | tail -n 1 | sed "s:^:    <badge>:;s:$:</badge>:"
				echo "  </game>"
			done < "$tmpfile"_st 
		else
			echo "$res" | sed -e "s;\(.*\)@\(.*\) achievements@\(.*\) points@Last played \(.*\);  <game>\n    <name>\1</name>\n    <achievements>\2</achievements>\n    <points>\3</points>\n    <lastplayed>\4</lastplayed>\n  </game>;"
		fi
		echo "</retroachievements>"
	else
		echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
		echo "<retroachievements>"
		echo "  <lastrefresh>$fn</lastrefresh>"
		echo "  <error>Player $USER hasn't unlocked any RetroAchievement yet</error>"
		echo "</retroachievements>"
	fi
	rm "$tmpfile" "$tmpfile"_2 "$tmpfile"_st "$tmpfile"_ba 2>/dev/null
}

#### Main loop
#
if [ $# -lt 1 ]; then
	[ -f "$CONFIGFILE" ] && USER=$(grep -E "^[ \t]*global.retroachievements.username=" "$CONFIGFILE" | cut -d= -f2 | uniq)
else
	tmp="$1"
	[ x"${tmp::1}" == "x-" ] && usage || USER="$1"
fi

[ x"$USER" == x ] && usage || process

